# -*- coding: utf-8 -*-
"""
******* 文档说明 ******

# 当前项目: Demo
# 创建时间: 2020-11-09  23:38
# 开发作者: Vincent
# 版    本: V1.0
"""
import time
import os
import sys
import logging


# 日志文件设置，可将日志文件分别打印到前端及日志中
def logger_set(path, f_level='DEBUG', s_level='DEBUG', name='main'):
    """
    :param path:      日志保存路径
    :param s_level:   控制台输出的日志级别默认为 DEBUG   # DEBUG，INFO，WARNING，ERROR，CRITICAL
    :param f_level:   日志文件输出的日志级别默认为 DEBUG   # DEBUG，INFO，WARNING，ERROR，CRITICAL
    :param name:      日志名称，默认为 'main'
    :return:          日志配置文件设置，无返回
    """

    # 创建一个logger
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)

    # 创建一个handler，用于写入日志文件 【默认为 DEBUG 级别】
    fh = logging.FileHandler(path, encoding='utf-8')
    if f_level == 'INFO':
        fh.setLevel(logging.INFO)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    elif f_level == 'WARNING':
        fh.setLevel(logging.WARNING)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    elif f_level == 'ERROR':
        fh.setLevel(logging.ERROR)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    elif f_level == 'CRITICAL':
        fh.setLevel(logging.CRITICAL)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    else:
        fh.setLevel(logging.DEBUG)  # DEBUG，INFO，WARNING，ERROR，CRITICAL

    # 创建一个handler，用于输出到控制台 【Level 可由用户设置，默认为 DEBUG 级别】
    sh = logging.StreamHandler()

    if s_level == 'INFO':
        sh.setLevel(logging.INFO)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    elif s_level == 'WARNING':
        sh.setLevel(logging.WARNING)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    elif s_level == 'ERROR':
        sh.setLevel(logging.ERROR)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    elif s_level == 'CRITICAL':
        sh.setLevel(logging.CRITICAL)  # DEBUG，INFO，WARNING，ERROR，CRITICAL
    else:
        sh.setLevel(logging.DEBUG)  # DEBUG，INFO，WARNING，ERROR，CRITICAL

    # 定义handler的输出格式
    formatter = '%(asctime)s %(name)s %(filename)s %(funcName)s %(lineno)4d %(levelname)-8s:  %(message)s'
    fh.setFormatter(logging.Formatter(formatter))

    formatter = '%(asctime)s %(levelname)-8s: %(message)s'
    sh.setFormatter(logging.Formatter(formatter))

    # 给logger添加handler
    logger.addHandler(fh)
    logger.addHandler(sh)


# 输入参数设置、全局参数、日志初始化
def argument_init(argv):
    import argparse

    # 模型版本信息
    version = 'V1.0.4'

    # ############################ CMD 传参 ################################################
    parser = argparse.ArgumentParser(
        description="""
        TensorFlow Bert Demo 代码

        ..............................................................................
        """,
        epilog="""
        ..............................................................................
        End help!  author:Vincent  2018-12-16 
        """)

    # required  参数是否为必须项【True|False】
    # nargs=     '+' 至少传入一个参数    '*' 传入0个或多个参数
    # default   默认值
    # help      帮助信息
    # type      参数属性默认都是字符串 【int|float|str】
    # choices   可选项 ['rock', 'paper', 'scissors']

    # 当前程序版本
    parser.add_argument('--version', action='version', version=version, help='the version of this code')

    # 备注信息
    parser.add_argument('--note', required=False, default='备注信息', help='模型备注信息')

    # 日志文件夹, 默认为当前目录下 _log 文件夹
    parser.add_argument('--dir_log', default='_log',
                        help='The log dir. ( Including Tensorboard )')

    # 控制台输出的日志级别默认为 DEBUG
    parser.add_argument('--log_level_s', default='INFO', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
                        help='控制台输出的日志级别默认为 DEBUG  [DEBUG,INFO,WARNING,ERROR,CRITICAL]')

    # 日志文件输出的日志级别默认为 DEBUG
    parser.add_argument('--log_level_f', default='INFO', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
                        help='日志文件输出的日志级别默认为 DEBUG  [DEBUG,INFO,WARNING,ERROR,CRITICAL]')

    args = parser.parse_args(argv[1:])

    # ##############################################################################################################
    # 模型版本信息
    args.Version = version

    # 开始时间 浮点型
    args.Start_time_float = time.time()
    # 开始时间 字符型
    # 时区差  当前时间为北京 东八区时间  此处操作为解决Docker中以 零时区 为标准而导致的时间混乱
    # time_zone = 8 - int(time.strftime('%z', time.localtime())) / 100
    # args.Start_time_str = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time() + time_zone * 60 * 60))
    args.Start_time_str = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))

    # 项目目录路径  【当前文件目录】
    args.CWD = os.path.abspath(os.path.join(os.path.dirname(__file__), "."))

    # ############################# 日志处理 ################################################
    # 若输入为绝对路径 并且 存在该文件夹 则日志保存到此目录下
    if os.path.isabs(args.dir_log) and os.path.exists(args.dir_log):
        args.P_Log = os.path.abspath(args.dir_log)
    else:
        args.P_Log = os.path.join(args.CWD, '_log')
        # 判断是否存在 存放日志 文件夹 log ，若无则重新创建
        os.makedirs(args.P_Log, exist_ok=True)

    # 若未创建日志，则创建日志 handler  【模型日志】
    if len(logging.getLogger('LoggerName').handlers) == 0:
        logger_file = os.path.join(os.path.join(args.P_Log, "LoggerName_{}.log".format(args.Start_time_str)))
        logger_set(path=logger_file, name='LoggerName', f_level=args.log_level_f, s_level=args.log_level_s)

    # 读取日志模块handler
    args.logger = logging.getLogger('LoggerName')

    # ############################# 打印用户输入超参数 #####################################
    args.logger.info('{}{:20s}{}'.format('* ' * 25, "     User Input   ", '* ' * 25))
    args.logger.info('{:15s}:{}'.format('Command', argv))  # 命令行传入参数

    user_input = ""
    for argv_i in argv:
        if argv_i.startswith("-"):
            if len(user_input.strip()) > 0:
                args.logger.info("Input: {}".format(user_input.strip()))
            user_input = ""
        user_input = user_input + "   " + argv_i
    args.logger.info("Input: {}".format(user_input.strip()))

    # ############################# 打印参数 ################################################
    # 读取 args 中的所有参数
    args_info = args.__dict__
    args.logger.info('{}{:20s}{}'.format('* ' * 25, "     Arguments    ", '* ' * 25))
    for i, args_i in enumerate(sorted(args_info)):
        args.logger.info('args_{:02d} ---  {:s} : {}'.format(i + 1, args_i, args_info[args_i]))
    # ############################# 系统参数 ################################################
    args.logger.info('{}{:20s}{}'.format('* ' * 25, "     System Info    ", '* ' * 25))

    import sys

    args.logger.info('{:15s}:{}'.format('PID ID', os.getpid()))  # 父进程ID
    args.logger.info('{:15s}:{}[win32/linux]'.format('Platform', sys.platform))  # 当前平台信息
    args.logger.info('{:15s}:{}'.format('System', sys.version.replace('\n', '  ')))
    args.logger.info('{:15s}:{}'.format('System', os.system('cat /etc/issue')))

    args.logger.info('{}'.format('- ' * 60))

    return args


# ##################################################################################
# 参数初始化
args = argument_init(sys.argv)

from flask import Flask
from flask import request
import json

app = Flask(__name__)


# 参数传输测试  UTF-8 编码格式
@app.route('/health', methods=['GET', 'POST'])
def health():
    args.logger.info('----------------------------------------------')
    args.logger.info('{:12s}: {}'.format('Method', request.method))
    args.logger.info('{:12s}: {}'.format('URL', request.url))
    args.logger.info('{:12s}: {}'.format('params', request.args))
    # args.logger.debug('{:12s}: {}'.format('Header', request.headers))
    args.logger.debug('{:12s}: {}'.format('Form', request.form))
    args.logger.info('{:12s}: {}'.format('Data', request.data.decode('utf_8')))
    args.logger.info('{:12s}: {}'.format('Data', request.get_data().decode('utf_8')))
    args.logger.debug('{:12s}: {}'.format('JSON', request.json))

    # 返回数据
    return_data = {'Code': '200',
                   'Info': '连接成功！',
                   'Time': time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(time.time()))}

    return json.dumps(return_data, ensure_ascii=False, sort_keys=True, indent=4)


if __name__ == '__main__':

    import flask
    args.logger.debug('flask Version:{}'.format(flask.__version__))

    app.run(host='0.0.0.0', port=8080, debug=False)
